import type {WebSocketMessage} from '@/types'

export class VoiceWebSocketService {
    private ws: WebSocket | null = null
    private url: string
    private reconnectAttempts = 0
    private maxReconnectAttempts = 5
    private reconnectDelay = 1000
    private webSocketSessionId: string | null = null
    private messageHandlers: Map<string, (data: any) => void> = new Map()
    private connectionCallbacks: {
        onOpen?: () => void
        onClose?: () => void
        onError?: (error: Event) => void
    } = {}
    private heartbeatInterval: number | null = null
    private heartbeatTimeout: number | null = null
    private lastHeartbeatTime = 0

    public getWebSocketSessionId(): string | null {
        return this.webSocketSessionId
    }

    constructor(url: string = 'ws://106.12.75.108:18004/ws/voice-chat') {
        this.url = url
    }

    // 连接WebSocket
    connect(callbacks?: {
        onOpen?: () => void
        onClose?: () => void
        onError?: (error: Event) => void
    }): Promise<void> {
        return new Promise((resolve, reject) => {
            try {
                this.connectionCallbacks = callbacks || {}
                this.ws = new WebSocket(this.url)

                this.ws.onopen = () => {
                    console.log('WebSocket连接已建立')
                    this.reconnectAttempts = 0
                    this.startHeartbeat()
                    this.connectionCallbacks.onOpen?.()
                    resolve()
                }

                this.ws.onmessage = (event) => {
                    this.handleMessage(event)
                }

                this.ws.onclose = () => {
                    console.log('WebSocket连接已关闭')
                    this.stopHeartbeat()
                    this.connectionCallbacks.onClose?.()
                    this.attemptReconnect()
                }

                this.ws.onerror = (error) => {
                    console.error('WebSocket错误:', error)
                    this.connectionCallbacks.onError?.(error)
                    reject(error)
                }
            } catch (error) {
                reject(error)
            }
        })
    }

    // 断开连接
    disconnect() {
        this.stopHeartbeat()
        if (this.ws) {
            this.ws.close()
            this.ws = null
        }
    }

    // 发送文本消息
    sendMessage(message: WebSocketMessage) {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify(message))
        } else {
            console.error('WebSocket未连接')
        }
    }

    // 发送二进制数据（音频）
    sendBinaryData(data: ArrayBuffer) {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(data)
        } else {
            console.error('WebSocket未连接')
        }
    }

    // 注册消息处理器
    onMessage(type: string, handler: (data: any) => void) {
        this.messageHandlers.set(type, handler)
    }

    // 移除消息处理器
    offMessage(type: string) {
        this.messageHandlers.delete(type)
    }

    // 处理接收到的消息
    private handleMessage(event: MessageEvent) {
        console.log('收到WebSocket消息:', event.data)
        console.log(typeof event.data)
        if (event.data instanceof Blob) {
            // 处理二进制数据（音频）
            this.handleBinaryMessage(event.data)
        } else {
            // 处理文本消息
            try {
                const message: WebSocketMessage = JSON.parse(event.data)

                if (message.type === 'connection') {
                    this.webSocketSessionId = message.sessionId
                    console.log('WebSocket连接成功，sessionId:', this.webSocketSessionId)
                }

                // 处理心跳响应
                if (message.type === 'heartbeat_response' || message.type === 'server_heartbeat') {
                    this.handleHeartbeatResponse(message)
                    return
                }

                const handler = this.messageHandlers.get(message.type)
                if (handler) {
                    handler(message)
                } else {
                    console.log('未处理的消息类型:', message.type, message)
                }
            } catch (error) {
                console.error('解析WebSocket消息失败:', error)
            }
        }
    }

    // 处理二进制消息（音频数据）
    private handleBinaryMessage(data: Blob) {
        console.log('收到二进制数据（音频数据）')
        const handler = this.messageHandlers.get('mp3_audio')
        if (handler) {
            handler(data)
        }
    }

    // 尝试重连
    private attemptReconnect() {
        if (this.reconnectAttempts < this.maxReconnectAttempts) {
            this.reconnectAttempts++
            console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`)

            setTimeout(() => {
                this.connect(this.connectionCallbacks)
            }, this.reconnectDelay * this.reconnectAttempts)
        } else {
            console.error('WebSocket重连失败，已达到最大重连次数')
        }
    }

    // 开始心跳
    private startHeartbeat() {
        this.stopHeartbeat() // 先停止之前的心跳

        // 每20秒发送一次心跳
        this.heartbeatInterval = window.setInterval(() => {
            if (this.isConnected) {
                this.sendMessage({
                    type: 'heartbeat',
                    timestamp: Date.now()
                })

                // 设置心跳超时检测
                this.heartbeatTimeout = window.setTimeout(() => {
                    console.warn('心跳超时，尝试重连')
                    this.disconnect()
                    this.attemptReconnect()
                }, 10000) // 10秒超时

            }
        }, 20000) // 20秒间隔
    }

    // 停止心跳
    private stopHeartbeat() {
        if (this.heartbeatInterval) {
            clearInterval(this.heartbeatInterval)
            this.heartbeatInterval = null
        }
        if (this.heartbeatTimeout) {
            clearTimeout(this.heartbeatTimeout)
            this.heartbeatTimeout = null
        }
    }

    // 处理心跳响应
    private handleHeartbeatResponse(message: WebSocketMessage) {
        this.lastHeartbeatTime = Date.now()

        // 清除心跳超时
        if (this.heartbeatTimeout) {
            clearTimeout(this.heartbeatTimeout)
            this.heartbeatTimeout = null
        }

        console.debug('收到心跳响应:', message.timestamp)
    }

    // 获取连接状态
    get isConnected(): boolean {
        return this.ws?.readyState === WebSocket.OPEN
    }

    // 获取最后心跳时间
    get lastHeartbeat(): number {
        return this.lastHeartbeatTime
    }
}

// 创建单例实例
export const voiceWebSocket = new VoiceWebSocketService()
